<?php

namespace App\Library;

class DBRSAUtil
{
    /**
     * 加签
     * @param $data
     * @return string 签名
     */
    public static function sign($data): string
    {
        $priKey = config('idRsa.privateKey');
        $res = openssl_get_privatekey($priKey);
        $sign = '';
        openssl_sign($data, $sign, $res);
        openssl_free_key($res);
        return base64_encode($sign);
    }

    /**
     * 验签
     * @param $data
     * @param $sign
     * @return bool 验签是否成功
     */
    public static function verify($data, $sign): bool
    {
        $pubKey = config('idRsa.publicKey'); //读取公钥文件
        $res = openssl_get_publickey($pubKey); //转换为openssl格式密钥
        $result = (bool)openssl_verify($data, base64_decode($sign), $res); //调用openssl内置方法验签，返回bool值
        openssl_free_key($res); //释放资源
        return $result;
    }

    /**
     * rsa加密
     * @param $data
     * @return string 加密后的密文
     */
    public static function rsaEncrypt($data): string
    {
        $pubKey = config('idRsa.publicKey'); //读取公钥文件
        $res = openssl_get_publickey($pubKey); //转换为openssl格式密钥
        $maxlength = DBRSAUtil::getMaxEncryptBlockSize($res);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_public_encrypt($input, $encrypted, $pubKey);
            $output .= $encrypted;
        }
        return base64_encode($output);
    }

    /**
     * 解密
     * @param string $data
     * @return string 解密后的明文
     */
    public static function rsaDecrypt(string $data): string
    {
        $priKey = config('idRsa.privateKey'); //读取私钥文件
        $res = openssl_get_privatekey($priKey); //转换为openssl格式密钥
        $data = base64_decode($data);
        $maxlength = self::getMaxDecryptBlockSize($res);
        $output = '';
        while ($data) {
            $input = substr($data, 0, $maxlength);
            $data = substr($data, $maxlength);
            openssl_private_decrypt($input, $out, $res);
            $output .= $out;
        }
        return $output;
    }

    /**
     * getMaxEncryptBlockSize
     * @param $keyRes
     * @return float|int
     */
    public static function getMaxEncryptBlockSize($keyRes): float|int
    {
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize / 8 - 11;
    }

    /**
     * getMaxDecryptBlockSize
     * 对于1024长度的RSA Key，返回值为128
     * @param $keyRes
     * @return float|int
     */
    public static function getMaxDecryptBlockSize($keyRes): float|int
    {
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize / 8;
    }
}
